\chapter{Instalacja i konfiguracja Neo4j}
%\chapterWithAuthor{Instalacja i konfiguracja Neo4j}{Michał Staroń}
\section{Instalacja i konfiguracja Neo4j}

Neo4j może być uruchomione jako integralna część tworzonej aplikacji, oddzielny serwer danych lub też rozmieszczone na wielu maszynach fizycznych lub wirtualnych w trybie High Availability.

\subsection{Instalacja serwera Neo4j}

Neo4j może zostać zainstalowane jako usługa systemowa lub jako program użytkowy. Aby zainstalować Neo4j ściągamy odpowiednią wersję ze strony \mbox{\url{http://neo4j.org/download}}. Następnie rozpakowujemy zawartość archiwum do wybranego katalogu. Aby uruchomić serwer bazy danych uruchamiamy:
\begin{itemize}
\item na Linux/MacOS: ./bin/neo4j start
\item na Windows: .\textbackslash bin\textbackslash Neo4j.bat start
\end{itemize}

Aby uruchomić serwer Neo4j jako usługę systemową w systemie Windows:

\begin{enumerate}
\item Otwieramy Wiersz Poleceń jako Administrator.
\item Uruchamiamy w katalogu, gdzie są wypakowane pliki: {\tt .\textbackslash bin\textbackslash Neo4j.bat install}
\end{enumerate}

\subsection{Neo4j jako integralna część aplikacji}

Neo4j może zostać załączone do kodu aplikacji poprzez dołączenie odpowiednich bibliotek Java. W czasie pisania programu odwołujemy się do API GraphDatabaseService\footnote{http://components.neo4j.org/neo4j/1.6.1/apidocs/org/neo4j/graphdb/GraphDatabaseService.html}. Aby wykorzystać tryb wysokiej dostępności zamiast EmbeddedGraphDatabase\footnote{http://components.neo4j.org/neo4j/1.6.1/apidocs/org/neo4j/kernel/EmbeddedGraphDatabase.html} używamy HighlyAvailableGraphDatabase\footnote{http://components.neo4j.org/neo4j-enterprise/1.6.1/apidocs/org/neo4j/kernel/HighlyAvailableGraphDatabase.html}.

\subsection{Tryb pracy rozproszonej}

Tylko wersja Neo4j Enterprise wspiera tryp pracy rozproszonej. W poniższej tabeli zostały przedstawione parametry konfiguracji trybu pracy rozproszonej:
\\
\begin{adjustwidth}{-4em}{-4em}
	\begin{center}
		\begin{tabular}{p{4cm}||p{4cm}|p{4cm}|p{2cm}}
			Nazwa Parametru & Wartość & Przykładowa wartość & Wymagany? \\ \hline
			ha.server_id & integer >= 0 & 1 & tak\\ \hline
			ha.server & (wykrywany automatycznie) domena i port, gdy działa jako master & my-domain.com:6001 & nie\\ \hline
			ha.coordinators & oddzielone przecinkiem  połączenia z coordinator & \mbox{localhost:2181}, \mbox{localhost:2182}, \mbox{localhost:2183} & tak\\ \hline
			ha.pull_interval & czas (w sekundach) pomiędzy kolejnymi odpytywaiami pomiędzy master i slave & 30 & nie\\ \hline
			ha.slave_coordinator_update_mode & tworzy element slave, który nigdy nie stanie się master & brak & nie\\ \hline
			ha.read_timeout & jak długo slave będzie czekał na odpowiedź master (domyślnie 20) & 20 & nie\\ \hline
			ha.lock_read_timeout & jak długo blokada przejęcia slave'a będzie aktywna (domyślnie wartość ha.read_timeout) & 40 & nie\\ \hline
			ha.zk_session_timeout & czas trwania sesji instancji w ZooKeeper & 30 & nie
		\end{tabular}
	\end{center}
\end{adjustwidth}

\subsubsection{Przykładowa konfiguracja Neo4j High Availability}
 Po ściągnięciu i rozpakowaniu wersji enterprise edytujemy plik ./conf/coord.cfg przypisując odpowiedni clientPort i~wpisując kolejno zakresy portów oraz adresy IP maszyn na których działa Coordinator. Plik ten bedzie identyczny dla trzech maszyn.

\begin{lstlisting}[style=snippet,language=bash]
#./conf/coord.cfg

...

server.1=192.168.1.201:2888:3888
server.2=192.168.1.201:2889:3889
server.3=192.168.1.201:2890:3890

...

clientPort=2181
\end{lstlisting}
Następnie tworzymy plik myid zawierający unikalny numer <id> zgdony z numerami użytymi wcześniej w server.<id>. Umieszczamy go w folderze ./data/coordinator/.

\begin{lstlisting}[style=snippet]
echo '1' > ./data/coordinator/myid
\end{lstlisting}

Możemy uruchomić usługi Coordinator na każdej z maszyn:

\begin{lstlisting}[style=snippet]
./bin/neo4j-coordinator start
\end{lstlisting}

W pliku ./conf/neo4j.properties wpisujemy adresy i porty usług Coordinator oraz przypisujemy odpowiednie numery id serwerom:

\begin{lstlisting}[style=snippet,language=bash]
#./conf/neo4j.properties
#unique server id for this graph database
#can not be negative id and must be unique
ha.server_id = 1
#ip and port for this instance to bind to
ha.server = localhost:6001
#connection information to the coordinator cluster client ports
ha.coordinators = 192.168.1.201:2181,192.168.1.202:2181,192.168.1.203:2181
\end{lstlisting}

W pliku ./conf/neo4j-server.properties aktywujemy tryb HA i jeśli uruchamiamy kilka usług Coordinator na tej samej maszynie odpowiednio modyfikujemy port:

\begin{lstlisting}[style=snippet,language=bash]
#./conf/neo4j-server.properties
...
# http port (for all data, administrative, and UI access)
org.neo4j.server.webserver.port=7474
...
# Allowed values:
# HA - High Availability
# SINGLE - Single mode, default.
# To run in High Availability mode, configure the coord.cfg file, and the
# neo4j.properties config file, then uncomment this line:
org.neo4j.server.database.mode=HA
\end{lstlisting}

Uruchamiamy wszystkie instancje serwera Neo4j:

\begin{lstlisting}[style=snippet]
./bin/neo4j start
\end{lstlisting}

Po uruchomieniu powinniśmy móc dostać się do wszystkich serwerów i sprawdzić status poprzez interfejs http://[adres_ip]:[port (domyślny:7474)]/webadmin/.
\begin{figure}
	\includegraphics{figures/webadmin.png}
	\caption{Interfejs zarządzania i monitorowania Neo4j.}
	\label{fig:webadmin}
\end{figure}

\section{Przykładowy kod programu}

Pierwszym elementem jest dołączenie bibliotek jar Neo4j do projektu z folderu ./lib/. Aby stworzyć lub otworzyć bazę danych tworzymy instancję  EmbeddedGraphDatabase\footnote{\url{http://components.neo4j.org/neo4j/1.6.1/apidocs/org/neo4j/kernel/EmbeddedGraphDatabase.html}}.

\begin{lstlisting}[style=snippet]
graphDb = new EmbeddedGraphDatabase( DB_PATH );
\end{lstlisting}

Aby zatrzymać działanie bazy Neo4j wywołujemy:

\begin{lstlisting}[style=snippet]
graphDb.shutdown();
\end{lstlisting}

\subsection{Hello World}

Typy relacji tworzone są z wykorzystaniem struktury enum. W tym przykładzie potrzebujemy tylko jednej wartości.

\begin{lstlisting}[style=snippet,language=Java]
private static enum RelTypes implements RelationshipType
{
    KNOWS
}
\end{lstlisting}

Deklarujemy niezbędne zmienne:

\begin{lstlisting}[style=snippet,language=Java]
GraphDatabaseService graphDb;
Node firstNode;
Node secondNode;
Relationship relationship;
\end{lstlisting}

Kolejny krok to uruchomienie serwera bazy danych. DB_PATH to ścieżka do bazy danych - jeśli nie istnieje plik zostanie on utworzony.

\begin{lstlisting}[style=snippet,language=Java]
graphDb = new EmbeddedGraphDatabase( DB_PATH );
\end{lstlisting}

Tworzymy graf składający się z dwóch węzłów połączonych jedną relacją oraz przypisanych im właściwości.

\begin{lstlisting}[style=snippet,language=Java]
firstNode = graphDb.createNode();
firstNode.setProperty( "message", "Hello, " );
secondNode = graphDb.createNode();
secondNode.setProperty( "message", "World!" );
relationship = firstNode.createRelationshipTo( secondNode, RelTypes.KNOWS );
relationship.setProperty( "message", "brave Neo4j " );
\end{lstlisting}

Nasz graf wygląda tak, jak przedstawiono na rysunku~\ref{fig:helloworld}.
\begin{figure}[scale=0.5]
	\includegraphics{figures/helloworld.png}
	\caption{Schemat grafu "Hello World"}
	\label{fig:helloworld}
\end{figure}

Usuwamy dane z bazy:

\begin{lstlisting}[style=snippet,language=Java]
firstNode.getSingleRelationship( RelTypes.KNOWS, Direction.OUTGOING ).delete();
firstNode.delete();
secondNode.delete();
\end{lstlisting}

Zamykamy bazę danych:

\begin{lstlisting}[style=snippet]
graphDb.shutdown();
\end{lstlisting}